1 /** 2 * Breadthfirst path finding algorithm 3 * 4 * License: 5 * D version of code is under MIT. The original is under Apache 2.0. 6 * 7 * The MIT License (MIT) 8 * 9 * Copyright (c) 2014 Devisualization (Richard Andrew Cattermole) 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining a copy 12 * of this software and associated documentation files (the "Software"), to deal 13 * in the Software without restriction, including without limitation the rights 14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 * copies of the Software, and to permit persons to whom the Software is 16 * furnished to do so, subject to the following conditions: 17 * 18 * The above copyright notice and this permission notice shall be included in all 19 * copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 * SOFTWARE. 28 * 29 * See_Also: 30 * http://www.redblobgames.com/pathfinding/a-star/implementation.html 31 */ 32 module devisualization.util.algorithms.pathfinding.breadthfirst; 33 import devisualization.util.algorithms.pathfinding.defs; 34 deprecated("Killing"): 35 36 /** 37 * Locates the next node in graph to get to a position 38 * 39 * Params: 40 * graph = The graph of nodes 41 * start = Starting/End position to go to 42 * 43 * Returns: 44 * An AA mapping a position to another to get to a point 45 */ 46 T[T] breadth_first_search(T)(Graph graph, T start) { 47 Queue!T frontier; 48 frontier.put(start); 49 T[T] came_from; 50 51 while(!frontier.empty) { 52 T current = frontier.get(); 53 foreach(next; graph.neighbors(current)) { 54 if (next !in came_from) { 55 frontier.put(next); 56 came_from[next] = current; 57 } 58 } 59 } 60 61 return came_from; 62 } 63 64 /** 65 * Locates the next node in graph to get to a position 66 * 67 * Params: 68 * graph = The graph of nodes 69 * start = Starting position to go to 70 * goal = The end position 71 * 72 * Returns: 73 * An AA mapping a position to another to get to a point 74 */ 75 T[T] breadth_first_search(T)(Graph graph, T start, T goal) { 76 Queue!T frontier; 77 frontier.put(start); 78 T[T] came_from; 79 80 while(!frontier.empty) { 81 T current = frontier.get(); 82 if (current == goal) 83 break; 84 85 foreach(next; graph.neighbors(current)) { 86 if (next !in came_from) { 87 frontier.put(next); 88 came_from[next] = current; 89 } 90 } 91 } 92 93 return came_from; 94 } 95 96 unittest { 97 Graph!string example_graph; 98 99 example_graph.edges = [ 100 "A": ["B"], 101 "B": ["A", "C", "D"], 102 "C": ["A"], 103 "D": ["E", "A"], 104 "E": ["B"] 105 ]; 106 107 breadth_first_search(example_graph, "A"); 108 109 // TODO: asserts 110 } 111 112 unittest { 113 SquareGrid!XY grid = SquareGrid!XY(30, 15); 114 grid.walls = DIAGRAM1_WALLS; 115 116 XY[] parents = breadth_first_search(grid, XY(8, 7)); 117 118 //TODO: asserts 119 } 120 121 unittest { 122 SquareGrid!XY grid = SquareGrid!XY(30, 15); 123 grid.walls = DIAGRAM1_WALLS; 124 125 XY[] parents = breadth_first_search(grid, XY(8, 7), XY(17, 2)); 126 127 //TODO: asserts 128 } 129 130 /** 131 * Locates the next node in graph to get to a position 132 * 133 * Params: 134 * graph = The graph of nodes 135 * start = Starting position to go to 136 * goal = The end position 137 * came_from = Output: An AA mapping a position to another to get to a point 138 * distance = Output: Distance of a node to the end point 139 * 140 * See_Also: 141 * http://www.redblobgames.com/pathfinding/tower-defense/ 142 */ 143 void breadth_first_search(T, U)(Graph graph, T start, T goal, out T[T] came_from, out U[T] distance) { 144 Queue!T frontier; 145 frontier.put(start); 146 distance[start] = 0; 147 148 while(!frontier.empty) { 149 T current = frontier.get(); 150 if (current == goal) 151 break; 152 153 foreach(next; graph.neighbors(current)) { 154 if (next !in came_from) { 155 frontier.put(next); 156 came_from[next] = current; 157 distance[next] = 1 + distance[current]; 158 } 159 } 160 } 161 }